package com.wxb.pm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wxb.pm.Exception.BusinessException;
import com.wxb.pm.Model.domain.Team;
import com.wxb.pm.Model.domain.User;
import com.wxb.pm.Model.domain.UserTeam;
import com.wxb.pm.Model.dto.TeamQuery;
import com.wxb.pm.Model.enums.TeamStatusEnum;
import com.wxb.pm.Model.requset.TeamJoinRequest;
import com.wxb.pm.Model.requset.TeamQuitRequest;
import com.wxb.pm.Model.requset.TeamUpdateRequest;
import com.wxb.pm.Model.vo.UserTeamVO;
import com.wxb.pm.Model.vo.UserVO;
import com.wxb.pm.common.ErrorCode;
import com.wxb.pm.mapper.TeamMapper;
import com.wxb.pm.service.TeamService;
import com.wxb.pm.service.UserService;
import com.wxb.pm.service.UserTeamService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
* @author 12796
 *
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2023-07-23 16:34:26
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{

    @Resource
    private UserService userService;

    @Resource
    private UserTeamService userTeamService;

    @Override
    @Transactional(rollbackFor = Exception.class) //事务注解，抛了异常事务就触发回滚
    public Long addTeam(Team team, User loginUser){
        //1.请求参数是否为空
        if (team ==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //2.是否登录
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }

        //3.判断队伍的人数是否太多,1-10
        int maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);
        if (maxNum < 1||maxNum>10){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍人数不符合");
        }

        //4.队伍标题
        String teamName = team.getTeamName();
        if (StringUtils.isAnyBlank(teamName) && teamName.length()>20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍标题过长");
        }
        //5.队伍描述可以为空
        String teamDescription = team.getDescription();
        if (StringUtils.isAnyBlank(teamDescription) || teamDescription.length()>512){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍描述过长");
        }
        //6.status是否公开,默认为0公开状态
        int status = Optional.ofNullable(team.getTeamStatus()).orElse(0);
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
        if (teamStatusEnum == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍不存在");
        }

        //7.队伍密码不能过长，加密队伍必须有密码
        String teamPassword = team.getTeamPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusEnum) && (StringUtils.isAnyBlank(teamPassword)||teamPassword.length()>32)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不合法");
        }
        //8.队伍超时时间在当前时间值前就队伍过期
        Date expireTime = team.getExpireTime();
        if (new Date().after(expireTime)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍过期");
        }
        //9.一个用户可以创建队伍不能太多，上限五个
        final long userId = loginUser.getId();
        QueryWrapper<Team> queryWrapper= new QueryWrapper<>();
        queryWrapper.eq("userId",userId);
        long TeamNum = this.count(queryWrapper);
        if (TeamNum >= 5){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍数量过多");
        }

        //10.插入队伍信息到队伍表
        team.setId(null);
        team.setUserId(userId);
        boolean result = this.save(team);
        if (!result){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"创建队伍失败");
        }
        //插入用户队伍表
        UserTeam userTeam = new UserTeam();
        userTeam.setJoinTime(new Date());
        userTeam.setUserId(userId);
        userTeam.setTeamId(team.getId());
        result = userTeamService.save(userTeam);
        if (!result){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"创建队伍失败");
        }
        return team.getId();
    }

    @Override
    public List<UserTeamVO> findAllTeam(TeamQuery teamQuery, boolean isAdmin) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if (teamQuery !=null){
            Long id = teamQuery.getId();
            if (id!=null){
                queryWrapper.eq("id",id);
            }
            //同时查询队伍名称和描述
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)){
                queryWrapper.and(qw->qw.like("teamName",searchText).or().like("description",searchText));
            }
            List<Long> idList = teamQuery.getIdList();
            if (CollectionUtils.isNotEmpty(idList)){
                queryWrapper.in("id",idList);
            }
            //根据队伍名查询
            String teamName = teamQuery.getTeamName();
            if (StringUtils.isNotBlank(teamName)){
                queryWrapper.like("teamName",teamName);
            }
            //根据描述查询
            String description = teamQuery.getDescription();
            if (StringUtils.isNotBlank(description)){
                queryWrapper.like("description",description);
            }
            //根据用户id查询队伍
            Long userId = teamQuery.getUserId();
            if (userId!=null &&userId >0 ){
                queryWrapper.eq("userId",userId);
            }
            //根据最大数查询
            Integer maxNum = teamQuery.getMaxNum();
            if (maxNum!=null && maxNum > 0){
                queryWrapper.eq("maxNum",maxNum);
            }
            //根据状态查询
            Integer teamStatus = teamQuery.getTeamStatus();
            TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(teamStatus);
            if (teamStatusEnum == null){
                teamStatusEnum = TeamStatusEnum.PUBLIC;
            }
            if (!isAdmin && teamStatusEnum.equals(TeamStatusEnum.PRIVATE)){
                throw new BusinessException(ErrorCode.NO_AUTH,"没有权限");
            }
            queryWrapper.eq("teamStatus",teamStatusEnum.getValue());

        }
        //不展示已经过期的队伍
        queryWrapper.and(qw -> qw.gt("expireTime",new Date()).or().isNull("expireTime"));

        List<Team> teamList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(teamList)){
            return new ArrayList<>();
        }
        //关联查询创建人信息
        List<UserTeamVO> userTeamVOList = new ArrayList<>();
        for (Team team : teamList) {
            Long userId = team.getUserId();
            if (userId == null){
                continue;
            }
            User user = userService.getById(userId);
            UserTeamVO userTeamVO = new UserTeamVO();
            BeanUtils.copyProperties(team,userTeamVO);
            if(user!=null){
                UserVO userVO = new UserVO();
                BeanUtils.copyProperties(user,userVO);
                userTeamVO.setCreatUser(userVO);
            }
            userTeamVOList.add(userTeamVO);
        }
        return userTeamVOList;
    }

    @Override
    public boolean updateTeam(TeamUpdateRequest teamUpdateRequest,User loginUser) {
        if (teamUpdateRequest ==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = teamUpdateRequest.getId();
        Team oldTeam = getTeamById(id);
        if (!oldTeam.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser) ){
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(teamUpdateRequest.getTeamStatus());
        if (teamStatusEnum.equals(TeamStatusEnum.SECRET)){
            if (StringUtils.isAnyBlank(teamUpdateRequest.getTeamPassword())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"加密状态密码不能为空");
            }
        }
        Team updateTeam = new Team();
        BeanUtils.copyProperties(teamUpdateRequest,updateTeam);
        return this.updateById(updateTeam);
    }

    @Override
    public boolean joinTeam(TeamJoinRequest teamJoinRequest,User loginUser) {
        if (teamJoinRequest ==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long teamId = teamJoinRequest.getTeamId();
        Team team = getTeamById(teamId);
        //队伍过期不可加入
        Date expireTime = team.getExpireTime();
        if (expireTime != null && expireTime.before(new Date())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍已过期");
        }
        //队伍私有，不可加入
        Integer teamStatus = team.getTeamStatus();
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(teamStatus);
        if (TeamStatusEnum.PRIVATE.equals(teamStatusEnum)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍为私有的");
        }

        //队伍加密，需要输入密码进去
        String teamPassword = teamJoinRequest.getTeamPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusEnum)){
            if (StringUtils.isAnyBlank(teamPassword) || !teamPassword.equals(team.getTeamPassword())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不匹配");
            }
        }
        //用户最多加入五个队伍
        Long userId = loginUser.getId();
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId",userId);
        long hasJoinNum = userTeamService.count(userTeamQueryWrapper);
        if (hasJoinNum > 5){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户最多创建和加入五个队伍");
        }
        //已加入队伍数量，只能加入未满的队伍
        if (teamHasUserNum(teamId) >= team.getMaxNum()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍已满");
        }
        //不能重复加入已加入的数量
        userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId",teamId);
        userTeamQueryWrapper.eq("userId",userId);
        long joinSameTeamNum = userTeamService.count(userTeamQueryWrapper);
        if (joinSameTeamNum>0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"已加入该队伍");
        }

        //新增队伍用户关联信息
        UserTeam userTeam = new UserTeam();
        userTeam.setJoinTime(new Date());
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        return userTeamService.save(userTeam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quitTeam(TeamQuitRequest teamQuitRequest, User loginUser) {
        if (teamQuitRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long teamId = teamQuitRequest.getTeamId();
        Team team = getTeamById(teamId);
        //判断该用户是否加入队伍
        Long userId = loginUser.getId();
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",userId);
        queryWrapper.eq("teamId",teamId);
        long count = userTeamService.count(queryWrapper);
        if (count == 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"未加入队伍");
        }
        //数量只有1 说明该用户为最后一人退出队伍
        if (teamHasUserNum(teamId) == 1){
            //删除队伍和删除队伍用户关系
            this.removeById(teamId);
        }else {
            //是否为队长
            if(team.getUserId().equals(userId)){
                //可以查出该队伍所有用户
                //是队长转移给最早加入的用户
                QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
                userTeamQueryWrapper.eq("teamId",teamId);
                userTeamQueryWrapper.last("order by id asc limit 2");
                List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
                if (CollectionUtils.isEmpty(userTeamList) || userTeamList.size() <=1){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR);
                }
                //新队长id获取
                UserTeam nextUserTeam = userTeamList.get(1);
                Long nextTeamUserId = nextUserTeam.getUserId();
                //更新队长
                Team updateTeam = new Team();
                updateTeam.setId(teamId);
                updateTeam.setUserId(nextTeamUserId);
                boolean result = this.updateById(updateTeam);
                if (!result){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR,"更新队伍队长失败");
                }
            }
        }
        return userTeamService.remove(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTeam(Long id,User loginUser) {
        //1.队伍是不是存在,
        Team team =  getTeamById(id);
        //2.校验是不是队长
        if(!team.getUserId().equals(loginUser.getId())){
            throw new BusinessException(ErrorCode.NO_AUTH,"无访问权限");
        }
        //3.移除所有加入队伍的关联信息
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId",id);
        boolean result = userTeamService.remove(userTeamQueryWrapper);
        if (!result){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"删除队伍信息失败");
        }
        //5.删除队伍
        return this.removeById(id);
    }


    /**
     * 某队伍拥有成员数量
     * @param teamId
     * @return
     */
    private long teamHasUserNum(long teamId){
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId",teamId);
        return userTeamService.count(userTeamQueryWrapper);
    }


    /**
     * 根据id获取队伍
     * @param teamId
     * @return
     */
    private Team getTeamById(Long teamId){
        if (teamId == null || teamId <=0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //队伍不存在
        Team team = this.getById(teamId);
        if (team == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍不存在");
        }
        return team;
    }
}




